package com.foo.designpattern.builder;

import junit.framework.TestCase;

/**
 * com.foo.designpattern.builder
 * Created with IntelliJ IDEA.
 * Created by jiang on 2016-05-04 16:17.
 *
 * @Description 测试类：建造者模式(Builder)
 * 建造者模式是对象的创建模式。建造者模式可以将一个产品的内部表象(internal representation)与产品的生产过程分割开来，
 * 从而可以使一个建造过程生成具有不同的内部表象的产品对象。
 * <p/>
 * 建造者模式涉及到四个角色：
 * 1、抽象建造者(Builder)角色：给出一个抽象接口，以规范产品对象的各个组成成分的建造。
 * 一般而言，此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者(ConcreteBuilder)角色。具体建造者类必须实现这个接口
 * 所要求的两种方法：一种是建造方法(buildPart)，另一种是返还结构方法(retrieveResult)。一般来说，产品所包含的零件数目与建造方法的
 * 数目相符。换言之，有多少零件就有多少相应的建造方法。
 * 2、具体建造者(ConcreteBuilder)角色：担任这个角色的是与应用程序紧密相关的一些类，它们在应用程序调用下创建产品的实例。这个角色要
 * 完成的任务包括两个：(1)实现抽象建造者Builder所声明的接口，给出一步一步地完成创建产品实例的操作；(2)在建造过程完成后，提供产品的实例。
 * 3、导演者(Director)角色：担任这个角色的类调用具体建造者角色以创建产品对象。应当指出的是，导演者角色并没有产品类的具体知识，真正
 * 拥有产品类的具体知识的是具体建造者角色。
 * 4、产品(Product)角色：产品便是建造中的复杂对象。一般来说，一个系统中会有多于一个的产品类，而且这些产品类并不一定有共同的接口，而
 * 可以是完全不相关联的。
 * <p/>
 * 导演者角色是与客户端打交道的角色。导演者将客户端创建产品的请求划分为对各个零件的建造请求，再将这些请求委派给具体建造者角色。
 * 具体建造者角色是做具体建造工作的，但是却不为客户端所知晓。
 * 一般来说，每有一个产品类，就有一个相应的具体建造者类。这些产品应当有一样数目的零件，而每有一个零件就相应的在所有的建造者角色里
 * 有一个建造方法。
 * <p/>
 * 建造者模式的优点：
 * 1、建造者模式的封装性很好。
 * 使用建造者模式可以有效的封装变化，在使用建造者模式的场景中，一般产品类和建造者类是比较稳定的，
 * 因此，将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
 * <p/>
 * 建造者模式适用场景：
 * 1、需要生产的产品对象有复杂的内部结构，每一个内部成分本身可以是对象，也可以仅仅是一个对象(即产品对象)的一个组成部分。
 * 2、需要生成的产品对象的属性相互依赖。建造者模式可以强制实行一种分步骤进行的建造过程，因此，如果产品对象的一个属性必须在另一个属性被
 * 赋值之后才可以被赋值，使用建造者模式是一个很好的设计思想。
 * 3、在对象创建过程中会使用到系统中的其他一些对象，这些对象在产品对象的创建过程中不易得到。
 * <p/>
 * 与工厂模式的比较：工厂模式关注的是创建单个产品，而建造者模式则关注创建复合对象。
 * 建造者模式将很多功能集成到一个类里，这个类可以创造出比较复杂的东西。
 */

public class BuilderTestCase extends TestCase {
    public void testBuilder() {
        System.out.println("= = = = ↓↓↓建造者模式，测试开始↓↓↓ = = = =");

        PersonDirector personDirector = new PersonDirector();

        Person man = personDirector.constructPerson(new ManBuilder());
        System.out.println(man.getHead());
        System.out.println(man.getBody());
        System.out.println(man.getFoot());

        Person lady = personDirector.constructPerson(new LadyBuilder());
        System.out.println(lady.getHead());
        System.out.println(lady.getBody());
        System.out.println(lady.getFoot());

        System.out.println("= = = = ↑↑↑建造者模式，测试结束↑↑↑ = = = =");
    }
}
